﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Xml;
using System.Windows.Forms;
using System.Collections;

using EBFHelper.Nodes;
using EBFHelper.forms;

namespace EBFHelper.EBFHelperUtil
{
    public static class HelperDisplayUtil
    {
        public static List<string> commServices = new List<string>();
        public static List<DataNode> commDataNodes = new List<DataNode>();
        public static List<DataNode> operationDataNodes = new List<DataNode>();
        public static string baseData = null;

        public static List<string> commContext = new List<string>();
        public static List<string> availableContext = new List<string>();

        private static XmlNodeList nodeList = null;
        private static List<XmlNode> availableKColls = new List<XmlNode>();

        public static List<string> commAvailableFmt = new List<string>();
        public static List<string> operationAvailableFmt = new List<string>();
        public static List<MyTreeNode> requestFmtNode = new List<MyTreeNode>();
        
        public static void checkProjectItemNode(EnvDTE.ProjectItems projectItems, List<EnvDTE.ProjectItem> pItems)
        {
            foreach (EnvDTE.ProjectItem pi in projectItems)
            {
                //判断是否为三个重要节点
                if (pi.Name.Equals("Actions") || pi.Name.Equals("Operations") || pi.Name.Equals("Opsteps") || pi.Name.Equals("Config"))
                {
                    pItems.Add(pi);
                }
                if (pItems.Count >= 4)
                {
                    break;//找到所有节点
                }
                //没有子节点
                if (pi.ProjectItems != null)
                {
                    checkProjectItemNode(pi.ProjectItems, pItems);
                }
            }
        }

        public static void findActionsAndOperationsAndOpstepsList(List<EnvDTE.ProjectItem> pItems, List<iNode> actionNodes, List<iNode> operationNodes,List<iNode> opStepNodes,List<iNode> commConfigNodes)
        {
            foreach (EnvDTE.ProjectItem pi in pItems)
            {
                //遍历ACTIONS文件夹中的每一个元素
                switch (pi.Name)
                {
                    case "Actions":
                        HelperDisplayUtil.findNodeList(pi, actionNodes, 0);
                        break;
                    case "Operations":
                        HelperDisplayUtil.findNodeList(pi, operationNodes, 1);
                        break;
                    case "Opsteps":
                        HelperDisplayUtil.findNodeList(pi,opStepNodes,2);
                        break;
                    case "Config":
                        HelperDisplayUtil.findNodeList(pi, commConfigNodes, 3);
                        break;
                    default:
                        break;
                }
               
            }
        }

        public static List<iNode> findXmlNodeList(List<iNode> iNodes)
        {
            List<iNode> xmlNodeList = new List<iNode>();
            foreach (iNode inode in iNodes)
            {
                if (!inode.projectItem.Name.EndsWith(".xml"))
                {
                    continue;
                }
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(inode.projectItem.FileNames[1]);
                ProjectNode pNode;
                if (null != (pNode = inode as ProjectNode) && xmlDoc.HasChildNodes)
                {
                    pNode.xmlDoc = xmlDoc;
                }
                xmlNodeList.Add(inode);
            }
            return xmlNodeList;
        }

        public static void buildTree(XmlNodeList xmlNodeList,TreeNodeCollection treeNodes,iNode inode)
        {
            string sValue;
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                if (xmlNode.NodeType == XmlNodeType.Element)  //只对element类型的节点进行处理
                {
                    MyTreeNode tNode = new MyTreeNode();
                    sValue = "";
                    for (int j = 0; j < xmlNode.Attributes.Count; j++)
                    {
                        sValue += xmlNode.Attributes[j].Name + "=" + xmlNode.Attributes[j].Value + ";";

                        tNode.attributes[xmlNode.Attributes[j].Name] = xmlNode.Attributes[j].Value;
                    }
                    tNode.name = xmlNode.Name;
                    tNode.Text = xmlNode.Name + ":" + sValue;
                    tNode.inode = inode;
                    treeNodes.Add(tNode);
                    XmlElement xmlElement = xmlNode as XmlElement;
                    if (inode.projectItem.Name.EndsWith("Op.xml"))
                    {
                        handleWithOperationDataNode(tNode, xmlElement);
                    }
                    else if (inode.projectItem.Name.Equals("EBContext.xml"))
                    {
                        handleWithEBContext(tNode, xmlElement);
                    }

                    if (xmlElement.HasAttribute("dataName"))
                    {
                        handleWithFmtDataName(tNode, xmlElement);
                    }

                    if (xmlElement.Name.Equals("refFormat") || xmlElement.Name.Equals("refFmt"))
                    {
                        requestFmtNode.Add(tNode);
                    }

                    if (xmlElement.Name.Equals("fmtDef") && tNode.inode.projectItem.Name.Equals("EBFormat.xml"))
                    {
                        string fmtId=xmlElement.GetAttribute("id");
                        if (!string.Empty.Equals(fmtId))
                        {
                            commAvailableFmt.Add(fmtId);
                        }
                    }
                    else if (xmlElement.Name.Equals("fmtDef") && tNode.inode.projectItem.Name.EndsWith("Op.xml"))
                    {
                        string fmtId = xmlElement.GetAttribute("id");
                        if (!string.Empty.Equals(fmtId))
                        {
                            operationAvailableFmt.Add(fmtId);
                        }
                    }
                    if (xmlNode.HasChildNodes)
                    {
                        buildTree(xmlNode.ChildNodes, tNode.Nodes,inode);
                    }
                }
                
            }
        }

        public static void addAutoCompleteStringCollectionFromXmlNodeList(List<iNode>XmlNodeList, AutoCompleteStringCollection ACSC)
        { 
            foreach (iNode inode in XmlNodeList)
            {
                ActionXmlNode actionXmlNode;
                if (null == (actionXmlNode = inode as ActionXmlNode))
                {
                    continue;
                }
                ACSC.Add(actionXmlNode.name);
            }
        }

        public static void addOperationXmlNodeToActionXmlNode(ActionXmlNode actionXmlNode,List<iNode> operationXmlList) 
        {
            string findString="/Action_Config/OperationAction";
            string attributeToBeFound = "operationName";
            string attribute = getAttributeFromXml(actionXmlNode.xmlDoc, findString,attributeToBeFound);
            if (string.IsNullOrEmpty(attribute))
            {
                return;
            }

            foreach (iNode inode in operationXmlList)
            {
                OperationXmlNode operationXmlNode;
                if (null == (operationXmlNode=inode as OperationXmlNode))
                {
                    continue;
                }
                XmlDocument operationXmlDoc = operationXmlNode.xmlDoc;
                XmlNode xmlNode = operationXmlDoc.SelectSingleNode("/Operation_Config/registry/field[@id='" + attribute + "']");
                if (null != xmlNode)
                {
                    actionXmlNode.operationXmlNode = operationXmlNode;
                    break;
                }
               
            }
        }

        public static void addOperationNodeAtrributeToAtrributeBox(MyTreeNode tNode,GroupBox AttributeBox,List<iNode> opStepXmlList,GroupBox opStepPathbox) 
        {
            showAttributesOfOperationXmlNode(tNode, AttributeBox,opStepXmlList,opStepPathbox);
        }

        public static void addActionNodeAttributeToAttributeWindow(XmlNodeList childNodes,ActionXmlNodeDetailInfo aXNDI) 
        {
            int i = 0;
            double scaleId = 0.05;
            double sacleSite = 0.70;
            int rangeId = (int)(scaleId * aXNDI.ForwardSiteBox.Width);
            int rangeSite = (int)(sacleSite * aXNDI.ForwardSiteBox.Width);
            int height = 24;
            int left = 0;
            int cross = rangeId;
            foreach (XmlNode xmlNode in childNodes)
            {
                if (xmlNode.NodeType == XmlNodeType.Element)//只对Element类型的的节点进行处理 
                {
                    switch (xmlNode.Name)
                    {
                        case "field" :
                            aXNDI.RegistryIdText.Text = xmlNode.Attributes[0].Value;
                            aXNDI.RegistryTypeText.Text = xmlNode.Attributes[1].Value;
                            break;
                        case "OperationAction":
                            aXNDI.ActionNameText.Text = xmlNode.Attributes[0].Value;
                            aXNDI.OperationNameText.Text = xmlNode.Attributes[1].Value;
                            aXNDI.BusinessCodeText.Text = xmlNode.Attributes[2].Value;
                            aXNDI.LocationText.Text = xmlNode.Attributes[3].Value;
                            break;
                        case "channelName":
                            aXNDI.ChannelText.Text = xmlNode.Attributes[0].Value;
                            break;
                        case "localeCode":
                            aXNDI.LanguageText.Text = xmlNode.Attributes[0].Value;
                            break;
                        case "forward":
                            TextBox tbID = new TextBox();
                            tbID.Text = xmlNode.Attributes[0].Value;
                            tbID.Width = rangeId;
                            tbID.Height = height;
                            tbID.Left = left;
                            tbID.Top =height+height * i;
                            TextBox tbFS = new TextBox();
                            tbFS.Text = xmlNode.Attributes[1].Value;
                            tbFS.Left = tbID.Right + cross;
                            tbFS.Width = rangeSite;
                            tbFS.Height = height;
                            tbFS.Top = tbID.Top;
                            aXNDI.ForwardSiteBox.Controls.Add(tbID);
                            aXNDI.ForwardSiteBox.Controls.Add(tbFS);
                            i++;
                            break;
                        default:
                            break;
                    }
                    if (xmlNode.HasChildNodes)
                    {
                        addActionNodeAttributeToAttributeWindow(xmlNode.ChildNodes,aXNDI);
                    }
                }
            }
        }

        public static void bindSourceToTextBox(ListBox listBox,object obj) 
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = obj;
            listBox.DataSource = bs;
            listBox.DisplayMember = "name";
        }

        public static void buildDiffrentTreesAccordingToDiffrentCommConfigs(iNode inode, TreeView treeView)
        {
            MyTreeNode tNode = new MyTreeNode();
            tNode.name = inode.name;
            tNode.Text = inode.name;
            tNode.inode = inode;
            buildTree(tNode.inode.xmlDoc.ChildNodes, tNode.Nodes, tNode.inode);
            if (treeView.Nodes.Count > 0)
            {
                treeView.Nodes.Clear();

            }
            treeView.Nodes.Add(tNode);
            treeView.ExpandAll();
        }

        public static void addCommDataNodes()
        {
            foreach (XmlNode kColl in availableKColls)
            {
                XmlNodeList kCollChildNodelist = kColl.ChildNodes;
                foreach (XmlNode kCollChildNode in kCollChildNodelist)
                {
                    if (kCollChildNode.NodeType == XmlNodeType.Element)
                    {
                        handleWithSingleDataNode(commDataNodes, (XmlElement)kCollChildNode, ((XmlElement)kColl).GetAttribute("id"));
                    }
                }
            }
        }

        public static void showAttributesOfOperationXmlNode(MyTreeNode tNode, GroupBox AttributeBox, List<iNode> opStepXmlList, GroupBox opStepPathbox)
        {
            int i = 0;                      //放在循环之外定义减少CPU负担
            double scaleKey = 0.15;
            double scaleValue = 0.60;
            int rangeKey = (int)(scaleKey * AttributeBox.Width);
            int rangeValue = (int)(scaleValue * AttributeBox.Width);
            int height = 24;
            int left = 0;
            int cross = rangeKey;

            foreach (DictionaryEntry de in tNode.attributes)
            {
                AttributeBox.Text = tNode.name;
                TextBox tbAN = new TextBox();
                tbAN.Text = de.Key.ToString();
                tbAN.Width = rangeKey;
                tbAN.Left = left;
                tbAN.Top = height + height * i;
                TextBox tbAV = new TextBox();
                tbAV.Text = de.Value.ToString();
                tbAV.Left = tbAN.Right + cross;
                tbAV.Width = rangeValue;
                tbAV.Top = tbAN.Top;
                AttributeBox.Controls.Add(tbAN);
                AttributeBox.Controls.Add(tbAV);
                i++;
            }
            if (tNode.Text.Contains("opStep"))
            {
                string text = tNode.Text;
                string[] str = text.Split(new char[] { ':', ';', '=' });

                string opStep = null;
                for (int j = 0; j < str.Length; j++)
                {
                    if (str[j].Equals("id"))
                    {
                        opStep = str[++j];
                        break;
                    }
                }
                if (!string.IsNullOrEmpty(opStep))
                {
                    XmlNode xmlNode = null;
                    foreach (iNode inode in opStepXmlList)
                    {
                        //if (inode.parentItem.Name.Equals(tNode.operationXmlNode.parentItem.Name))
                        //{
                        XmlDocument xmlDoc = inode.xmlDoc;
                        xmlNode = xmlDoc.SelectSingleNode("/OpStep_Config/kColl/kColl/field[@id='" + opStep + "']");
                        if (null != xmlNode)
                        {
                            break;
                        }

                        //}
                    }
                    if (null != xmlNode)
                    {
                        if (xmlNode.NodeType != XmlNodeType.Element)
                        {
                            return;
                        }
                        XmlElement xmlElement = (XmlElement)xmlNode;
                        TextBox tbOSN = new TextBox();
                        tbOSN.Text = opStep;
                        tbOSN.Width = rangeKey;
                        tbOSN.Height = height;
                        tbOSN.Left = 0;
                        tbOSN.Top = height;
                        TextBox tbOSFP = new TextBox();
                        tbOSFP.Text = xmlElement.GetAttribute("value");
                        tbOSFP.Width = rangeValue;
                        tbOSFP.Left = tbOSN.Right + cross;
                        tbOSFP.Top = tbOSN.Top;
                        opStepPathbox.Controls.Add(tbOSN);
                        opStepPathbox.Controls.Add(tbOSFP);
                    }
                }

            }
        }

        public static void showAttributesOfCommConfigsXmlNode(MyTreeNode tNode, GroupBox AttributeBox)
        {
            int i = 0;                      //放在循环之外定义减少CPU负担
            double scaleKey = 0.15;
            double scaleValue = 0.60;
            int rangeKey = (int)(scaleKey * AttributeBox.Width);
            int rangeValue = (int)(scaleValue * AttributeBox.Width);
            int height = 24;
            int left = 0;
            int cross = rangeKey;

            foreach (DictionaryEntry de in tNode.attributes)
            {
                AttributeBox.Text = tNode.name;
                TextBox tbAN = new TextBox();
                tbAN.Text = de.Key.ToString();
                tbAN.Width = rangeKey;
                tbAN.Left = left;
                tbAN.Top = height + height * i;
                TextBox tbAV = new TextBox();
                tbAV.Text = de.Value.ToString();
                tbAV.Left = tbAN.Right + cross;
                tbAV.Width = rangeValue;
                tbAV.Top = tbAN.Top;
                AttributeBox.Controls.Add(tbAN);
                AttributeBox.Controls.Add(tbAV);
                i++;
            }
        }

        private static void findNodeList(EnvDTE.ProjectItem parentItem, List<iNode> iNodes, int style)
        {
            foreach (EnvDTE.ProjectItem pi in parentItem.ProjectItems)
            {
                switch (style)
                {
                    case 0:
                        ActionXmlNode actionXmlNode = new ActionXmlNode();
                        actionXmlNode.projectItem = pi;
                        actionXmlNode.parentItem = parentItem;
                        actionXmlNode.name = pi.Name;
                        iNodes.Add(actionXmlNode);
                        break;
                    case 1:
                        OperationXmlNode operationXmlNode = new OperationXmlNode();
                        operationXmlNode.projectItem = pi;
                        operationXmlNode.parentItem = parentItem;
                        operationXmlNode.name = pi.Name;
                        iNodes.Add(operationXmlNode);
                        break;
                    case 2:
                        OpStepXmlNode opStepXmlNode = new OpStepXmlNode();
                        opStepXmlNode.projectItem = pi;
                        opStepXmlNode.parentItem = parentItem;
                        opStepXmlNode.name = pi.Name;
                        iNodes.Add(opStepXmlNode);
                        break;
                    case 3:
                        CommConfigXmlNode commConfigXmlNode = new CommConfigXmlNode();
                        if (pi.Name.Contains("EB") && pi.Name.EndsWith(".xml"))
                        {
                            commConfigXmlNode.projectItem = pi;
                            commConfigXmlNode.parentItem = parentItem;
                            commConfigXmlNode.name = pi.Name;
                            XmlDocument xmlDoc = new XmlDocument();
                            xmlDoc.Load(commConfigXmlNode.projectItem.FileNames[1]);
                            if (xmlDoc.HasChildNodes)
                            {
                                commConfigXmlNode.xmlDoc = xmlDoc;

                                switch (commConfigXmlNode.name)
                                {
                                    case "EBData.xml":
                                        commContext.Clear();
                                        addDataNodes(commConfigXmlNode.xmlDoc);
                                        break;
                                    case "EBService.xml":
                                        commServices.Clear();
                                        addServices(commConfigXmlNode.xmlDoc);
                                        break;
                                    default:
                                        break;
                                }

                            }
                            iNodes.Add(commConfigXmlNode);
                        }
                        break;
                    default:
                        break;
                }
                if (pi.ProjectItems != null)
                {
                    findNodeList(pi, iNodes, style);
                }
            }

        }

        private static string getAttributeFromXml(XmlDocument xmlDoc,string findString,string attributeToBeFound)
        {
            XmlNode ebOperation = xmlDoc.SelectSingleNode(findString);
            if (null == ebOperation)
            {
                return "";
            }
            XmlElement xn = (XmlElement)ebOperation;
            string attribute = xn.GetAttribute(attributeToBeFound);
            if (string.IsNullOrEmpty(attribute))
            {
                return "";
            }
            return attribute;
        }

        private static void addOpStepsToOperation(OperationXmlNode operationXmlNode, List<iNode> opStepXmlList) 
        {

        }

       

        private static void addDataNodes(XmlDocument xmlDoc)
        {
            nodeList = xmlDoc.SelectNodes("/Data_Configs/kColl");
            foreach (XmlNode xmlNode in nodeList)
            {
                XmlElement xmlElement = null;
                if (null == (xmlElement = xmlNode as XmlElement))
                {
                    continue;
                }

                string parent = xmlElement.GetAttribute("id");
                if (!commContext.Contains(parent))
                {
                    commContext.Add(parent);
                }

            }
           
        }

        private static void handleWithSingleDataNode(List<DataNode> dataNodes,XmlElement xmlElement, string parent)
        {   
                DataNode dataNode = new DataNode();
                if (!string.IsNullOrEmpty(xmlElement.GetAttribute("id")) && xmlElement.Name.Equals("field"))
                {
                    dataNode.id = xmlElement.GetAttribute("id");
                    dataNode.value = xmlElement.GetAttribute("value");
                    dataNode.parent = parent;
                    dataNodes.Add(dataNode);
                }
                else if (!string.IsNullOrEmpty(xmlElement.GetAttribute("refId")))
                {
                    foreach (XmlNode kColl in nodeList)
                    {
                        if (xmlElement.GetAttribute("refId").Equals(((XmlElement)kColl).GetAttribute("id")))
                        {
                            foreach (XmlNode kCollChildNode in kColl.ChildNodes)
                            {
                                if (kCollChildNode.NodeType==XmlNodeType.Element)
                                {
                                    handleWithSingleDataNode(dataNodes, (XmlElement)kCollChildNode, ((XmlElement)kColl).GetAttribute("id"));
                                }
                            }
                            break;
                        }
                    }
                }
                else if (xmlElement.Name.Equals("iColl"))
                {
                    dataNode.id = xmlElement.GetAttribute("id");
                    dataNode.value = "interdata";
                    dataNode.parent = parent;
                }
        }

        private static void addServices(XmlDocument xmlDoc)
        {
            XmlNode xmlNode = xmlDoc.SelectSingleNode("/Service_Configs");
            if (null == xmlNode)
            {
                return;
            }
            foreach (XmlNode xmlChildNode in xmlNode.ChildNodes)
            {
                XmlElement xmlChildElement = null;
                if (null == (xmlChildElement = xmlChildNode as XmlElement))
                {
                    continue;
                }
                string service = xmlChildElement.GetAttribute("id");
                if (!string.IsNullOrEmpty(service))
                {
                    commServices.Add(service);
                }
            }
        }

        private static void handleWithOperationDataNode(MyTreeNode tNode,XmlElement xmlElement)
        {
            if (xmlElement.HasAttribute("baseData"))
            {
                baseData = xmlElement.GetAttribute("baseData");
            }
            if (xmlElement.HasAttribute("value") && xmlElement.Name.Equals("field"))
            {
                XmlNode parentNode = xmlElement.ParentNode;
                XmlElement parentElement = (XmlElement)parentNode;

                foreach (DataNode node in commDataNodes)
                {
                    if (node.id.Equals(xmlElement.GetAttribute("id")))
                    {
                        tNode.ForeColor = Color.FromName("Blue");
                        node.value = xmlElement.GetAttribute("value");
                        break;
                    }
                }
                string parent = parentElement.GetAttribute("id");
                foreach (DataNode operationDataNode in operationDataNodes)
                {
                    if (operationDataNode.id.Equals(xmlElement.GetAttribute("id")) && operationDataNode.parent.Equals(parent))
                    {
                        tNode.ForeColor= Color.FromName("Red");
                        tNode.Text="重复定义"+tNode.Text;
                        break;
                    }
                }
                handleWithSingleDataNode(operationDataNodes,xmlElement, parent);
            }
        }

        private static void handleWithEBContext(MyTreeNode tNode,XmlElement xmlElement)
        {
            if (xmlElement.Name.Equals("refService"))
            {
                string service = xmlElement.GetAttribute("refId");
                if (!string.Empty.Equals(service) && !commServices.Contains(service))
                {
                    tNode.ForeColor = Color.FromName("Red");
                    tNode.Text = "服务不存在" + tNode.Text;
                }
            }
            else if (xmlElement.Name.Equals("refKColl"))
            {
                string refData = xmlElement.GetAttribute("refId");
                if (!string.Empty.Equals(refData))
                {
                    if (!commContext.Contains(refData))
                    {
                        tNode.ForeColor = Color.FromName("Red");
                        tNode.Text = "错误的引用" + tNode.Text;
                    }
                    else
                    {
                        availableContext.Add(refData);
                        foreach (XmlNode kColl in nodeList)
                        {
                            if (((XmlElement)kColl).GetAttribute("id").Equals(refData)
                                || ((XmlElement)kColl).GetAttribute("id").Equals("business"))
                            {
                                availableKColls.Add(kColl);
                                break;
                            }
                        }
                        
                    }
                }
                else
                {
                    tNode.ForeColor = Color.FromName("Red");
                    tNode.Text = "格式错误" + tNode.Text;
                }

            }

        }

        private static void handleWithFmtDataName(MyTreeNode tNode,XmlElement xmlElement)
        {
                        bool isCommData = false;
                        bool isOperationData = false;
                        string dataName = xmlElement.GetAttribute("dataName");
                        if (!availableContext.Contains("business"))
                        {
                            availableContext.Add("business");
                        }

                        if (dataName.Contains("."))
                        {
                            string[] str = dataName.Split(new char[] { '.' });
                            foreach (DataNode node in commDataNodes)
                            {
                                if (node.id.Equals(str[1]) && node.parent.Equals(str[0]))
                                {
                                    isCommData = true;
                                    break;
                                }
                            }
                            foreach (DataNode node in operationDataNodes)
                            {
                                if (node.id.Equals(str[1]) && node.parent.Equals(str[0]))
                                {
                                    isOperationData = true;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (DataNode node in commDataNodes)
                            {
                                if (node.id.Equals(dataName))
                                {
                                    isCommData = true;
                                    break;
                                }
                            }
                            foreach (DataNode node in operationDataNodes)
                            {
                                if (node.id.Equals(dataName))
                                {
                                    isOperationData = true;
                                    break;
                                }
                            }
                        }

                        if (!isCommData && !isOperationData)
                        {
                            tNode.ForeColor = Color.FromName("Red");
                            tNode.Text = "未定义的数据" + tNode.Text;
                            tNode.Parent.ForeColor = Color.FromName("Red");
                            MyTreeNode parent = (MyTreeNode)tNode.Parent;
                            while (!parent.Text.Contains("fmtDef"))
                            {
                                parent = (MyTreeNode)parent.Parent;
                            }
                            parent.ForeColor = Color.FromName("Red");
                        }
        }
    }
}
